package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {
        String cartKey = getCartKey(userId);
        CartInfo cartInfoExit = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (cartInfoExit != null) {
            Integer num = cartInfoExit.getSkuNum() + skuNum>200?200:cartInfoExit.getSkuNum() + skuNum;
            cartInfoExit.setSkuNum(num);
            if (cartInfoExit.getIsChecked() == 0) {
                cartInfoExit.setIsChecked(1);
            }
            cartInfoExit.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExit.setUpdateTime(new Date());

        } else {
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfoExit = new CartInfo();
            cartInfoExit.setSkuId(skuId);
            cartInfoExit.setUserId(userId);
            cartInfoExit.setSkuNum(skuNum);
            cartInfoExit.setCartPrice(skuInfo.getPrice());
            cartInfoExit.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExit.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExit.setSkuName(skuInfo.getSkuName());
            cartInfoExit.setCreateTime(new Date());
            cartInfoExit.setUpdateTime(new Date());
        }
        redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExit);
    }

    /**
     * 查看购物车
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        //创建未登录购物车集合
        List<CartInfo> cartNoLoginList = new ArrayList<>();
        //创建缓存key
        String cartKey = "";
        //查看未登录情况下的购物车
        if (!StringUtils.isEmpty(userTempId)) {
            cartKey = getCartKey(userTempId);
            cartNoLoginList = redisTemplate.boundHashOps(cartKey).values();
        }
        if (StringUtils.isEmpty(userId)) {
            if (!CollectionUtils.isEmpty(cartNoLoginList)) {
                cartNoLoginList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(), Calendar.SECOND));
            }
            return cartNoLoginList;
        }

        //创建登录或者合并后的购物车集合
        List<CartInfo> cartInfoList = new ArrayList<>();
        if (!StringUtils.isEmpty(userId)) {
            cartKey = getCartKey(userId);
            BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
            if (!CollectionUtils.isEmpty(cartNoLoginList)) {
                cartNoLoginList.forEach(cartInfoNoLogin -> {
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())) {
                        //说明存在相同的商品
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                        Integer num = Math.min(cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum(), 200);
                        cartInfoLogin.setSkuNum(num);
                        cartInfoLogin.setSkuPrice(productFeignClient.getSkuPrice(cartInfoLogin.getSkuId()));
                        cartInfoLogin.setUpdateTime(new Date());
                        if (cartInfoNoLogin.getIsChecked() == 1) {
                            if (cartInfoLogin.getIsChecked() == 0) {
                                cartInfoLogin.setIsChecked(1);
                            }
                        }
                        boundHashOperations.put(cartInfoLogin.getSkuId().toString(),cartInfoLogin);
                    } else {
                        //不存在相同的商品
                        cartInfoNoLogin.setCreateTime(new Date());
                        cartInfoNoLogin.setUpdateTime(new Date());
                        cartInfoNoLogin.setUserId(userId);
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                });
                redisTemplate.delete(getCartKey(userTempId));
            }
            cartInfoList = boundHashOperations.values();
            if (!CollectionUtils.isEmpty(cartInfoList)) {
                cartInfoList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(), Calendar.SECOND));
            }
        }
        return cartInfoList;
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked, String userId) {
        if (!StringUtils.isEmpty(userId)) {
            String cartKey = getCartKey(userId);
            CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());
            if (cartInfo != null) {
                cartInfo.setIsChecked(isChecked);
                redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfo);
            }
        }
    }

    @Override
    public void allCheckCart(Integer isChecked,String userId) {
        if (!StringUtils.isEmpty(userId)) {
            String cartKey = getCartKey(userId);
            List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
            Map<String, CartInfo> map = cartInfoList.stream().map(cartInfo -> {
                cartInfo.setIsChecked(isChecked);
                return cartInfo;
            }).collect(Collectors.toMap(cartInfo -> cartInfo.getSkuId().toString(), cartInfo -> cartInfo));
            redisTemplate.opsForHash().putAll(cartKey,map);
        }
    }

    /**
     * 删除购物车
     * @param skuId
     * @param userId
     */
    @Override
    public void deleteCart(Long skuId, String userId) {
        if (!StringUtils.isEmpty(userId)) {
            String cartKey = getCartKey(userId);
            redisTemplate.opsForHash().delete(cartKey, skuId.toString());
        }
    }

    /**
     * 清空购物车
     * @param userId
     */
    @Override
    public void clearCart(String userId) {
        if (!StringUtils.isEmpty(userId)) {
            String cartKey = getCartKey(userId);
            redisTemplate.delete(cartKey);
        }
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId.toString());
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            List<CartInfo> list = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).collect(Collectors.toList());
            return list;
        }
        return null;
    }

    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
